<?php

namespace common\models\db;

use fztadmin\behaviors\RBAC;
use wodrow\yii2wtools\tools\Security;
use wodrow\yii2wtools\tools\Tree;
use Yii;
use wodrow\yii2wtools\tools\ArrayHelper;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;
use yii\web\IdentityInterface;
use yiithings\softdelete\SoftDelete;

/**
 * This is the model class for table "{{%user}}".
 *
 * @author
 * @property-read array $statusDesc
 * @property-read string $avatarImage
 * @property AdminRole[] $adminRoles
 * @property Custom $custom
 */
class User extends \common\models\db\tables\User implements IdentityInterface
{
    const SCENARIO_TEST = 'test';
    const STATUS_ACTIVE = 10;
    const IS_ADMIN_SUPER_TRUE = 1;
    const IS_ADMIN_SUPER_FALSE = 0;

    public function getStatusDesc()
    {
        return [
            self::STATUS_ACTIVE => "正常",
        ];
    }

    public function getIsAdminSuperDesc()
    {
        return [
            self::IS_ADMIN_SUPER_TRUE => "是",
            self::IS_ADMIN_SUPER_FALSE => "否",
        ];
    }

    use SoftDelete;

    public function getAvatarImage()
    {
        return THIS_SERVER_BASE_URI."/static/images/no-avatar.png";
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors = ArrayHelper::merge($behaviors, [
            'timestamp' => [
                'class' => TimestampBehavior::class,
                'createdAtAttribute' => false,
                'updatedAtAttribute' => false,
            ],
            'blameable' => [
                'class' => BlameableBehavior::class,
                'createdByAttribute' => false,
                'updatedByAttribute' => false,
            ],
            'softdelete' => [
                'class' => 'yiithings\softdelete\behaviors\SoftDeleteBehavior',
            ],
        ]);
        return $behaviors;
    }

    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['token' => $token]);
    }

    public function getId()
    {
        return $this->id;
    }

    public function getAuthKey()
    {
        return $this->auth_key;
    }

    public function validateAuthKey($authKey)
    {
        return $authKey == $this->auth_key;
    }

    /**
     * @param $username
     * @return User|null
     */
    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username]);
    }

    public function setPassword($password)
    {
        $this->password = md5($password);
        $this->pwd = Security::thinkEncrypt($password);
        $this->key = \Yii::$app->security->generateRandomString();
//        $this->auth_key = \Yii::$app->security->generateRandomString();
    }

    public function validatePassword($password)
    {
        return md5($password) == $this->password;
    }

    public function setPayPassword($pay_password)
    {
        $this->$pay_password = md5($pay_password);
        $this->pay_pwd = Security::thinkEncrypt($pay_password);
        $this->key = \Yii::$app->security->generateRandomString();
//        $this->auth_key = \Yii::$app->security->generateRandomString();
    }

    public function validatePayPassword($pay_password)
    {
        return md5($pay_password) == $this->$pay_password;
    }

    public function generateToken()
    {
        $this->token = \Yii::$app->security->generateRandomString(17).YII_BT_MTIME;
        if (static::findOne(['token' => $this->token])){
            $this->generateToken();
        }
        $this->key = \Yii::$app->security->generateRandomString();
        $this->auth_key = \Yii::$app->security->generateRandomString();
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios = ArrayHelper::merge($scenarios, [
            self::SCENARIO_TEST => [],
        ]);
        return $scenarios;
    }

    public function rules()
    {
        $rules = parent::rules();
        /*foreach ($rules as $k => $v) {
            if ($v[1] == 'required'){
                $rules[$k][0] = array_diff($rules[$k][0], ['created_at', 'updated_at', 'created_by', 'updated_by']);
            }
        }*/
        $rules = ArrayHelper::merge($rules, [
//            [[], 'required', 'on' => self::SCENARIO_TEST],
        ]);
        return $rules;
    }

    public function attributeLabels()
    {
        $attributeLabels = parent::attributeLabels();
        $attributeLabels = ArrayHelper::merge($attributeLabels, [
            'avatar' => "头像",
            'nickname' => "昵称",
            'status' => "状态",
            'created_at' => "创建时间",
        ]);
        return $attributeLabels;
    }

    public function beforeValidate()
    {
        if (parent::beforeValidate()){
            // TODO: Change the autogenerated stub
            return true;
        }else{
            return false;
        }
    }

    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)){
            $this->checkLoginField();
            return true;
        }else{
            return false;
        }
    }

    public function beforeDelete()
    {
        if (parent::beforeDelete()){
            // TODO: Change the autogenerated stub
            return true;
        }else{
            return false;
        }
    }

    public function afterFind()
    {
        parent::afterFind();
    }

    public function afterSave($insert, $changedAttributes)
    {
        parent::afterSave($insert, $changedAttributes);
        // TODO: Change the autogenerated stub
    }

    public function afterValidate()
    {
        parent::afterValidate();
        // TODO: Change the autogenerated stub
    }

    public function afterRefresh()
    {
        parent::afterRefresh();
        // TODO: Change the autogenerated stub
    }

    public function afterDelete()
    {
        parent::afterDelete();
        // TODO: Change the autogenerated stub
    }

    public function checkLoginField()
    {
        if ($this->phone || $this->email || $this->username) {
            return true;
        }else{
            throw new \Exception("用户名，手机号，邮箱至少一项不为空");
        }
    }

    public function test()
    {
        $test = self::instance();
        $test->setScenario(self::SCENARIO_TEST);
        $test->save();
        var_dump($test->toArray());
    }

    public function getNickName()
    {
        return $this->nickname?:$this->username;
    }

    public function getAdminRoles()
    {
        return $this->hasMany(AdminRole::class, ['id' => "admin_role_id"])->viaTable(AdminUserRole::tableName(), ['user_id' => 'id']);
    }

    public function getAdminRoleIds()
    {
        $ids = [];
        foreach ($this->adminRoles as $k => $v) {
            $ids[] = $v->id;
        }
        return $ids;
    }

    public function getAdminRoleNames()
    {
        $names = [];
        foreach ($this->adminRoles as $k => $v) {
            $names[] = $v->name;
        }
        return $names;
    }

    /**
     * @return AdminPower[]
     */
    public function getAdminPowers()
    {
        $custom = $this->custom;
        $ids = [];
        $l1 = AdminRolePower::find()->where(['in', 'admin_role_id', $this->getAdminRoleIds()])->all();
        foreach ($l1 as $k => $v) {
            $ids[] = $v->admin_power_id;
        }
        $l2 = [];
        if ($l1){
            $l2 = AdminPower::find()->where(['in', 'id', $ids])->all();
        }
        $l3 = [];
        foreach ($l2 as $k => $v) {
            if (!$custom){
                if (in_array($v->route, RBAC::$mustHasCustomUseRoutes)){
                    continue;
                }
            }
            $l3[] = $v;
        }
        return $l3;
    }

    public function getAdminPowerIds()
    {
        $ids = [];
        foreach ($this->getAdminPowers() as $k => $v){
            $ids[] = $v->id;
        }
        return $ids;
    }

    /**
     * @return AdminPower[]
     */
    public function getCheckedAdminPowers($toArray = 0)
    {
        $list = [];
        foreach (AdminPower::getAllPowers() as $k => $v) {
            if (in_array($v->id, $this->getAdminPowerIds())){
                $v->isChecked = 1;
            }
            $list[] = $toArray?$v->toArray():$v;
        }
        return  $list;
    }

    /**
     * @return array
     */
    public function getAdminPowerRoutes()
    {
        $routes = [];
        $list = $this->getAdminPowers();
        foreach ($list as $k => $v) {
            $routes[] = $v->route;
        }
        return $routes;
    }

    /**
     * @return AdminPower[]
     */
    public function getAdminMenus()
    {
        $list = [];
        foreach ($this->getAdminPowers() as $k => $v) {
            if ($v->type == AdminPower::TYPE_MENU){
                $list[] = $v;
            }
        }
        return $list;
    }

    public function getAdminMenuIds()
    {
        $ids = [];
        foreach ($this->getAdminMenus() as $k => $v){
            $ids[] = $v->id;
        }
        return $ids;
    }

    /**
     * @return AdminPower[]
     */
    public function getAdminFuns()
    {
        $list = [];
        foreach ($this->getAdminPowers() as $k => $v) {
            if ($v->type == AdminPower::TYPE_FUN){
                $list[] = $v;
            }
        }
        return $list;
    }

    public function getAdminFunIds()
    {
        $ids = [];
        foreach ($this->getAdminFuns() as $k => $v){
            $ids[] = $v->id;
        }
        return $ids;
    }

    public function getAdminMenuFunTree()
    {
        $menus = $this->getAdminMenus();
        $funs = $this->getAdminFuns();
        return AdminPower::generateMenuFunTree($menus, $funs);
    }

    public function getCheckedAdminMenuFunTree()
    {
        $menus = $funs = [];
        foreach (AdminPower::getAllPowers() as $k => $v) {
            $power = $v->toArray();
            if (in_array($v->id, $this->getAdminPowerIds())){
                $power['isChecked'] = 1;
            }else{
                $power['isChecked'] = 0;
            }
            switch ($v->type){
                case AdminPower::TYPE_MENU:
                    $menus[] = $power;
                    break;
                default:
                    $funs[] = $power;
                    break;
            }
        }
        return AdminPower::generateMenuFunTree($menus, $funs);
    }

    public function getAdminMenuTree()
    {
        if ($this->is_admin_super){
            return AdminPower::getAdminMenuFunTree(1);
        }else{
            return $this->getAdminMenuFunTree();
        }
    }

    public function canRoute($route)
    {
        if ($this->is_admin_super){}else{
            if (in_array($route, RBAC::$ignoreCheckRoutes)) {
                return true;
            }
            if (!in_array($route, $this->getAdminPowerRoutes())){
                return false;
            }
        }
        return true;
    }

    /**
     * @return \yii\db\ActiveQuery|Custom|null
     */
    public function getCustom()
    {
        return $this->hasOne(Custom::class, ['bind_user_id' => 'id']);
    }
}
